﻿Imports System.IO

Namespace Items

    ''' <summary>
    ''' Represents a type of item that is a song.
    ''' </summary>
    Public Class SongItem
        Inherits BaseItem

        Private FSongID As Guid = Nothing

        ''' <summary>
        ''' Gets or sets the song ID.
        ''' </summary>
        ''' <value>The unique ID of the song.</value>
        Public Property SongID() As Guid
            Get
                If FSongID = Nothing Then Throw New ApplicationException("No ID has been set for this song.")
                Return FSongID
            End Get
            Set(ByVal value As Guid)
                If FSongID <> Nothing Then Throw New ApplicationException("An ID has already been set for this song.")
                FSongID = value
            End Set
        End Property

        ''' <summary>
        ''' Gets or sets the authors of the song.
        ''' </summary>
        ''' <value>The song's authors.</value>
        Public Property Authors() As List(Of String) = New List(Of String)

        Private FCategories As New List(Of Guid)

        ''' <summary>
        ''' Gets the categories the song is assigned to.
        ''' </summary>
        ''' <value>The list of categories the song is assigned to.</value>
        Public ReadOnly Property Categories() As List(Of Guid)
            Get
                Return FCategories
            End Get
        End Property

        ''' <summary>
        ''' Initializes a new instance of the <see cref="SongItem" /> class.
        ''' </summary>
        Public Sub New()

        End Sub

        ''' <summary>
        ''' Initializes a new instance of the <see cref="SongItem" /> class.
        ''' </summary>
        ''' <param name="title">The title of the song.</param>
        ''' <param name="parts">The parts / verses that make up the song.</param>
        Public Sub New(ByVal title As String, ByVal ParamArray parts() As String)
            MyBase.Title = title
            For Each Part As String In parts
                Me.Parts.Add(Part)
            Next
        End Sub

        ''' <summary>
        ''' Loads the song from the specified file name.
        ''' </summary>
        ''' <param name="fileName">Name of the file to load.</param>
        ''' <returns>A song item, whose contents are defined in the specified file.</returns>
        Public Shared Function Load(ByVal fileName As String) As SongItem

            Using File As New FileStream(fileName, FileMode.Open)
                Dim SongID As Guid = New Guid(IO.Path.GetFileNameWithoutExtension(fileName))
                Return Load(File, SongID)
            End Using

        End Function

        ''' <summary>
        ''' Loads the song from the specified array of bytes.
        ''' </summary>
        ''' <param name="data">The data that represents the song.</param>
        ''' <param name="songID">The ID of the song.</param>
        ''' <returns>A song item, whose contents are defined in the specified byte array.</returns>
        Public Shared Function Load(data As Byte(), songID As Guid) As SongItem

            Using Reader As New MemoryStream(data)
                Return Load(Reader, songID)
            End Using

        End Function

        ''' <summary>
        ''' Loads the song from the specified stream.
        ''' </summary>
        ''' <param name="stream">The stream containing the song.</param>
        ''' <param name="songID">The ID of the song.</param>
        ''' <returns>A song item, whose contents are defined in the specified stream.</returns>
        Public Shared Function Load(stream As Stream, songID As Guid) As SongItem

            ' Open the file
            Using File As New BinaryReader(stream)

                ' Get the ID of the song
                Dim Result As New SongItem
                Result.SongID = songID

                ' Keep reading the file
                While File.BaseStream.Position < File.BaseStream.Length

                    ' Read the name of the next datum
                    Select Case File.ReadString

                        Case "TITLE"
                            Result.Title = File.ReadString

                        Case "AUTHOR"
                            Result.Authors.Add(File.ReadString)

                        Case "COPYRIGHTLINE"
                            Result.CopyrightLine = File.ReadString

                        Case "PART"
                            Result.Parts.Add(File.ReadString)

                    End Select
                End While

                ' Return the song
                Return Result

            End Using

        End Function

        ''' <summary>
        ''' Saves the song to the specified file name.
        ''' </summary>
        ''' <param name="fileName">Name of the file to write the song to.</param>
        Public Sub Save(ByVal fileName As String)

            ' Create a new file
            Dim File As New BinaryWriter(New FileStream(fileName, FileMode.Create))

            ' Write title
            File.Write("TITLE")
            File.Write(MyBase.Title)

            ' Write list of authors
            For Each Author As String In Me.Authors
                File.Write("AUTHOR")
                File.Write(Author)
            Next

            ' Write parts
            For Each Part As String In MyBase.Parts
                File.Write("PART")
                File.Write(Part)
            Next

            ' Write copyright details
            File.Write("COPYRIGHTLINE")
            File.Write(MyBase.CopyrightLine)

            ' Close the file
            File.Close()

        End Sub

    End Class

End Namespace